package self.zhangkang.chart.view.avg.index

import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import self.zhangkang.chart.data.KLineInfo
import self.zhangkang.chart.tools.CanvasTools
import self.zhangkang.chart.tools.NumberFormatUtils
import self.zhangkang.chart.view.IndexLineInfo
import self.zhangkang.chart.view.IndexNameConfig
import self.zhangkang.chart.view.avg.AvgChartIndex
import self.zhangkang.chart.view.avg.AvgIndexInfo
import self.zhangkang.chart.view.avg.AvgViewColor
import self.zhangkang.chart.view.avg.AvgViewDimen
import self.zhangkang.chart.view.pool.PathPool
import self.zhangkang.chart.view.pool.RectPool

/**
 * @author : Android-张康
 * created on: 2023/5/9 18:19
 * description: 分时-成交量
 */
internal class AvgVolume(
    private val pathPool: PathPool,
    private val rectPool: RectPool,
    private val avgViewColor: AvgViewColor,
    private val avgViewDimen: AvgViewDimen,
    private val indexNameConfig: IndexNameConfig
) : AvgIndexInfo {

    private val indexLineInfoPath = mutableMapOf<IndexLineInfo, Path>()

    private var maxValue: Long = 0

    private var minValue: Long = 0

    private var priceItem: Float = 0.0F

    private var volumeWidth: Float = 0.0F

    /**
     * 计算空值
     */
    override fun calculationEmpty() {
        maxValue = 0
        minValue = 0
    }

    /**
     * 获取指标类型
     */
    override fun getIndexInfo(): AvgChartIndex {
        return AvgChartIndex.AvgVolume
    }

    /**
     * 获取占的比例
     */
    override fun getProportion(): Int {
        return 1
    }

    /**
     * 计算最大值前
     *
     * @param kLineInfo 第一个值
     */
    override fun calculationMaxAndMinBefore(kLineInfo: KLineInfo) {
        maxValue = 0
    }

    /**
     * 计算最大值
     *
     * @param kLineInfo 当前值
     */
    override fun calculationMaxAndMin(kLineInfo: KLineInfo) {
        if (kLineInfo.volume > maxValue) {
            maxValue = kLineInfo.volume
        }
    }

    /**
     * 计算最大值后
     */
    override fun calculationMaxAndMinAfter() {

    }

    /**
     * 绘制背景
     *
     * @param canvas 画布
     * @param startX 开始X
     * @param startY 开始Y
     * @param stopX 结束X
     * @param stopY 结束Y
     * @param linePaint 画布
     * @param textPaint 画布
     */
    override fun drawBackground(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopX: Float,
        stopY: Float,
        linePaint: Paint,
        textPaint: Paint
    ) {
        val halfLine = avgViewDimen.borderLineStrokeWidth / 2
        val backgroundPath = pathPool.acquire().apply {
            moveTo(startX + halfLine, startY)
            lineTo(stopX - halfLine, startY)
            lineTo(stopX - halfLine, stopY)
            lineTo(startX + halfLine, stopY)
            close()
        }
        canvas.drawPath(backgroundPath, linePaint)
        pathPool.release(backgroundPath)
        //绘制最高价
        textPaint.textSize = avgViewDimen.subplotOrdinateTextSize
        textPaint.color = avgViewColor.subplotOrdinateTextColor
        val maxValueText = NumberFormatUtils.numberFormat(maxValue.div(100))
        val mTextBoundsRect = rectPool.acquire()
        textPaint.getTextBounds(maxValueText, 0, maxValueText.length, mTextBoundsRect)
        val textStartY = mTextBoundsRect.height() + avgViewDimen.textPaddingLine + startY
        canvas.drawText(
            maxValueText,
            startX + avgViewDimen.textPaddingLine,
            textStartY,
            textPaint
        )
        rectPool.release(mTextBoundsRect)
    }

    /**
     * 绘制当前值
     *
     * @param canvas 画布
     * @param startX 开始的 X
     * @param startY 开的的 Y
     * @param stopX 结束的 X
     * @param stopY 结束的 Y
     * @param linePaint 线的画笔
     * @param textPaint 文字的画笔
     * @param marginTop 距离顶部的距离
     * @param span
     * @param indexValueHorizontalSpace 指标值之间的横向距离
     * @param indexValueVerticalSpace 指标值之间的纵向距离
     * @param kLineInfo 当前的值
     * @param kLineIsLine K线是否为一条线
     */
    override fun drawCurrentIndexInfo(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopX: Float,
        stopY: Float,
        linePaint: Paint,
        textPaint: Paint,
        marginTop: Float,
        span: Int,
        indexValueHorizontalSpace: Float,
        indexValueVerticalSpace: Float,
        kLineInfo: KLineInfo,
        kLineIsLine: Boolean
    ) {
        //先绘制指标名称
        val indicatorNameWidth = CanvasTools.drawIndicatorName(
            canvas = canvas,
            startX = startX,
            startY = startY,
            stopY = stopY,
            linePaint = linePaint,
            textPaint = textPaint,
            rectPool = rectPool,
            indicatorName = "成交量",
            indexNameConfig = indexNameConfig,
            hasArrowDropDown = false,
        )
        val currentValue = kLineInfo.volume.div(100)
        //小于1万展示全部，大于等于1万，展示格式化后的
        val drawText = if (currentValue < 10000) {
            currentValue.toString()
        } else {
            NumberFormatUtils.numberFormat(currentValue)
        }
        textPaint.color = avgViewColor.normalValueTextColor
        textPaint.textSize = avgViewDimen.currentValueTextSize
        val valueTextStartX = startX + indicatorNameWidth + indexValueHorizontalSpace
        CanvasTools.drawTextInVerticalCenter(
            canvas = canvas,
            startX = valueTextStartX,
            startY = startY,
            stopY = stopY,
            text = drawText,
            textPaint = textPaint,
            rectPool = rectPool
        )
    }

    /**
     * 绘制当前值内容之前
     *
     * @param canvas 画布
     * @param startX 开始的 X
     * @param startY 开的的 Y
     * @param stopX 结束的 X
     * @param stopY 结束的 Y
     * @param paint 画笔
     * @param candlestickWidth 蜡烛的宽度
     * @param candlestickWidthSpace 蜡烛之间的距离
     * @param kLineInfo 当前的值
     * @param kLineIsLine K线是否为一条线
     */
    override fun beforeDrawItemContent(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopX: Float,
        stopY: Float,
        paint: Paint,
        candlestickWidth: Float,
        candlestickWidthSpace: Float,
        kLineInfo: KLineInfo,
        kLineIsLine: Boolean
    ) {
        val volumeSpace: Float = if (kLineIsLine) {
            0F
        } else {
            avgViewDimen.volumeRectSpace
        }
        val volumeRange = maxValue - minValue
        val drawHeight = stopY - startY
        priceItem = drawHeight / volumeRange
        volumeWidth = candlestickWidth + candlestickWidthSpace - volumeSpace
    }

    /**
     * 绘制当前值内容
     *
     * @param canvas 画布
     * @param startX 开始的 X
     * @param startY 开的的 Y
     * @param stopX 结束的 X
     * @param stopY 结束的 Y
     * @param textPaint 文字的画笔
     * @param linePaint 线的画笔
     * @param kLineInfo 当前的值
     * @param isFirst 是否为第一次
     * @param yangLineIsFill 阳线是否实心
     * @param totalTranslateX X轴总的位移
     * @param candlestickWidth 蜡烛的宽度
     * @param halfCandlestickWidth 蜡烛的一半宽度
     * @param kLineIsLine K线是否为一条线
     */
    override fun drawItemContent(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopX: Float,
        stopY: Float,
        textPaint: Paint,
        linePaint: Paint,
        kLineInfo: KLineInfo,
        isFirst: Boolean,
        yangLineIsFill: Boolean,
        totalTranslateX: Float,
        candlestickWidth: Float,
        halfCandlestickWidth: Float,
        kLineIsLine: Boolean
    ) {
        //最高价格的 Y 坐标
        val volumeY = priceItem * (maxValue - kLineInfo.volume) + startY
        //Path 的横坐标
        var pathX = halfCandlestickWidth + totalTranslateX
        if (pathX < 0) {
            pathX = halfCandlestickWidth
        }
        indexLineInfoPath.forEach {
            val maValue = it.key.getIndexValue(kLineInfo)
            val maY = priceItem * (maxValue - maValue) + startY
            val path = it.value
            if (isFirst) {
                if (maY <= stopY) {
                    path.moveTo(pathX, maY)
                } else {
                    path.moveTo(pathX, stopY)
                }
            } else {
                if (maY < stopY) {
                    path.lineTo(pathX, maY)
                }
            }
        }
        //判断当前绘制的颜色
        val candlestickColor = if (kLineInfo.closePrice > kLineInfo.openPrice) {
            if (!yangLineIsFill) {
                linePaint.style = Paint.Style.STROKE
            }
            avgViewColor.redColor
        } else if (kLineInfo.closePrice < kLineInfo.openPrice) {
            linePaint.style = Paint.Style.FILL_AND_STROKE
            avgViewColor.greenColor
        } else {
            linePaint.style = Paint.Style.FILL_AND_STROKE
            avgViewColor.greenColor
        }
        linePaint.color = candlestickColor
        linePaint.strokeWidth = avgViewDimen.borderLineStrokeWidth
        val rectLeft: Float = if (totalTranslateX > 0) {
            startX - avgViewDimen.volumeRectSpace
        } else {
            startX
        }
        val rectRight: Float = if (isFirst) {
            rectLeft + volumeWidth - avgViewDimen.borderLineStrokeWidth * 2
        } else {
            rectLeft + volumeWidth
        }
        //绘制矩形
        canvas.drawRect(startX, volumeY, rectRight, stopY, linePaint)
    }

    /**
     * 绘制完整个当前内容之后
     *
     * @param canvas 画布
     * @param paint 画笔
     */
    override fun afterDrawItemContent(canvas: Canvas, paint: Paint) {
        indexLineInfoPath.forEach {
            val maColor = it.key.getLineColor()
            val maPath = it.value
            paint.color = maColor
            canvas.drawPath(maPath, paint)
            pathPool.release(maPath)
        }
        indexLineInfoPath.clear()
    }

    /**
     * 获取当前左边的值
     *
     * @param percentage 比例
     *
     * @return 返回当前左边坐标的值
     */
    override fun getCurrentLeftValue(percentage: Float): String {
        val currentValue = getCurrentValue(percentage)
        return NumberFormatUtils.numberFormat(currentValue)
    }

    override fun getCurrentRightValue(percentage: Float): String? {
        return null
    }

    private fun getCurrentValue(percentage: Float): Long {
        if (percentage >= 1.0F) {
            return maxValue
        }
        if (percentage <= 0.0F) {
            return minValue
        }
        return ((maxValue - minValue) * percentage).toLong()
    }
}